package com.qixin.modules.eaStandard.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qixin.modules.ea.mapper.EaSysUserMapper;
import com.qixin.modules.ea.vo.EaSysUser;
import com.qixin.modules.eaApplication.entity.EaEntertainApply;
import com.qixin.modules.eaApplication.entity.EaHostObject;
import com.qixin.modules.eaApplication.mapper.EaEntertainApplyMapper;
import com.qixin.modules.eaApplication.mapper.EaHostObjectMapper;
import com.qixin.modules.eaBasic.entity.EaRegion;
import com.qixin.modules.eaBasic.mapper.EaRegionMapper;
import com.qixin.modules.eaBasic.util.ChangeIdToNameUtil;
import com.qixin.modules.eaStandard.entity.*;
import com.qixin.modules.eaStandard.mapper.*;
import com.qixin.modules.eaStandard.service.IEaStandardService;
import com.qixin.modules.eaStandard.vo.EaEntertainCheckVo;
import com.qixin.modules.eaStandard.vo.EaStandardVo;
import com.qixin.modules.rzInvoice.entity.*;
import com.qixin.modules.rzInvoice.mapper.*;
import org.jeecg.common.util.EmptyUtil;
import org.jeecg.modules.nc.entity.NcPersonnel;
import org.jeecg.modules.nc.mapper.NcPersonnelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author:wly
 * @Date:2021/9/8
 * @Describtion: 发票校验是否符合报销标准
 */
@Service
public class EaTravelCheckImpl implements IEaStandardService {
    @Autowired
    private EaStandardsettingMapper eaStandardsettingMapper;
    @Autowired
    private EaTrainstandardMapper eaTrainstandardMapper;
    @Autowired
    private EaHotelstandardMapper eaHotelstandardMapper;
    @Autowired
    private EaSysUserMapper eaSysUserMapper;
    @Autowired
    private EaRegionMapper eaRegionMapper;
    @Autowired
    private EaAirplanestandardMapper eaAirplanestandardMapper;
    @Autowired
    private EaBillMapper eaBillMapper;
    @Autowired
    private EaBillItemMapper eaBillItemMapper;
    @Autowired
    private EaHotelstandarddtlMapper eaHotelstandarddtlMapper;
    @Autowired
    private ChangeIdToNameUtil changeIdToNameUtil;
    @Autowired
    private EaHotelbookspersondMapper eaHotelbookspersondMapper;
    @Autowired
    private EaHostObjectMapper eaHostObjectMapper;
    @Autowired
    private EaEntertainApplyMapper eaEntertainApplyMapper;
    @Autowired
    private EaCommunicationstandardMapper eaCommunicationstandardMapper;
    @Autowired
    private NcPersonnelMapper ncPersonnelMapper;

    //判断是否制定报销标准-入口类
    @Override
    public Map<String,Object> check(EaStandardVo eaStandardVo){
        //判断具体标准
        Map<String,Object> standardResult = checkstandardsettingByType(eaStandardVo);
        return standardResult;
    }

    //判断火车标准是否控制
    //判断报销控制标准
    //判断报销人(明细的费用归属人)火车标准,[刚性控制,允许提交,不能超标][柔性控制,允许提交,金额只能填写最大标准金额]
    //是否例外(暂时不控制),????????????????????????
    //报销人(明细的费用归属人)关联的用户是先用用户查询标准是否存在,不存在再去查询用户相应的(部门/职级/职务)标准是否存在

    //不允许乘坐高铁,允许乘坐高铁[商务座/一等座/二等座/特等座/无座]
    //不允许乘坐动车,允许乘坐动车[软卧/动卧/一等座/二等座/无座]
    //不允许乘坐普通列车,允许乘坐普通列车[软卧/硬卧/硬座/无座/高级软卧/软座]

    //判断酒店标准是否控制
    //判断报销人(明细的费用归属人)酒店标准,[刚性控制,允许提交,不能超标][柔性控制,允许提交,金额只能填写最大标准金额]
    //根据酒店明细,查询具体城市相应的报销标准[旺季标准],如果没有记录就去查询(一线城市/二线城市/三线城市/四线城市/港澳台地区)的标准
    //是否为统一标准,统一标准后,一线城市/二线城市/三线城市/四线城市/港澳台地区都使用统一标准金额
    //报销人(明细的费用归属人)关联的用户是先用用户查询标准是否存在,不存在再去查询用户相应的(部门/职级/职务)标准是否存在
    private Map<String, Object> checkstandardsettingByType(EaStandardVo eaStandardVo) {
        String fpid = eaStandardVo.getFpid();  //发票id
        EaBill eaBill = eaBillMapper.selectById(fpid);
        String xflx = eaBill.getKind();//消费类型:餐饮1、/交通2、/住宿3、/通用4
        String fygsr = eaStandardVo.getFygsrid();  //费用归属人

        Map<String,Object> map = new HashMap<String,Object>();
        BigDecimal reversalAmount = new BigDecimal(0);   //实际金额

        // 人员档案信息
        NcPersonnel ncPersonnel = ncPersonnelMapper.selectById(fygsr);
        // 人员级别 1、省公司正职负责人 2、特殊人才 3、其余人员
        String level = ncPersonnel.getLevel().toString();

        //根据发票类型,判断所属标准是否控制
        if(xflx.equals("3")){  // 住宿发票
            map.put("code","0");
            map.put("message","");   //提示信息
            map.put("reversalAmount",eaBill.getTotal());        //实际金额
            map.put("controlintensity",false);   //是否柔性控制
            return map;

//            String message = "";     //返回信息
//            Map<String,Object> persondParams = new HashMap<String,Object>();
//            persondParams.put("pid",fpid);
//            List<EaHotelbookspersond> eaHotelbookspersondList = eaHotelbookspersondMapper.selectByMap(persondParams);
//            if(eaHotelbookspersondList != null && eaHotelbookspersondList.size() > 0) {
//                for (int i = 0; i < eaHotelbookspersondList.size(); i++) {
//                    EaHotelbookspersond eaHotelbookspersond = eaHotelbookspersondList.get(i);
//                    // personnelid 是人员主键
//                    String personnelid = eaHotelbookspersond.getPersonnelid();   // 入住人
//
//                    //通过人住人找到对应用户id
//                    String userId = eaSysUserMapper.queryUserIdByPsnid(personnelid);
//
//                    eaStandardVo.setFygsrid(userId);
//
//                    //查询报销部门/职级/职务
//                    EaSysUser sysUser2 = eaSysUserMapper.selectById(userId);
//                    String deptid2 = sysUser2.getDepartIds();  //部门
//                    String postid2 = sysUser2.getPost();  //职务id
//                    String userIdentity2 = EmptyUtil.checkNull(sysUser2.getUserIdentity());  //职级
//
//                    map = checkJdbz(eaStandardVo,deptid2,postid2,userIdentity2,eaHotelbookspersond);
//
//                    Boolean controlintensity2 = map.get("controlintensity") != null ? (Boolean) map.get("controlintensity") : false;   //是否柔性
//                    if(!map.get("message").equals("")){
//                        if(message.equals("")){
//                            if(controlintensity2 == true){    //其中一条是柔性控制就返回柔性控制
//                                message = map.get("message").toString() + "柔性控制,调整报销金额为标准金额";   //将所有提示信息拼接在一起
//                            }else{
//                                message = map.get("message").toString();   //将所有提示信息拼接在一起
//                            }
//                        }else{
//                            if(controlintensity2 == true){    //其中一条是柔性控制就返回柔性控制
//                                message = message + "\r\n" + map.get("message") + "柔性控制,调整报销金额为标准金额";   //将所有提示信息拼接在一起
//                            }else{
//                                message = message + "\r\n" + map.get("message");   //将所有提示信息拼接在一起
//                            }
//                        }
//                    }
//                    String reversalAmount2 = map.get("reversalAmount") != null ? map.get("reversalAmount").toString() : "0";
//                    reversalAmount = reversalAmount.add(new BigDecimal(reversalAmount2));     //将入住明细的金额加起来就是实际金额
//                }
//            }
//            map.put("reversalAmount",reversalAmount);        //实际金额
//            map.put("message",message);                      //提示信息
//            return map;
        }else if(xflx.equals("2")){//交通
            map = checkJtbz(eaStandardVo);
            return map;
        }else{// 餐饮
            map.put("code","0");
            map.put("message","未设置标准，可报销!");   //提示信息
            map.put("reversalAmount",eaBill.getTotal());        //实际金额
            map.put("controlintensity",false);   //是否柔性控制
            return map;
        }
    }

    //酒店
    private Map<String, Object> checkJdbz(EaStandardVo eaStandardVo,String deptid,String postid,String userIdentity,EaHotelbookspersond eaHotelbookspersond){
        Map<String,Object> map = new HashMap<String,Object>();

        //根据用户去查标准
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("relationtype",1);
        queryWrapper.like("personnelid",eaStandardVo.getFygsrid());
        List<Map<String,Object>> eaStandardseList = eaHotelstandardMapper.selectMaps(queryWrapper);
        if(eaStandardseList.size() > 0){//个人有指定酒店标准
            EaHotelstandard eaHotelstandard = JSON.parseObject(JSON.toJSONString(eaStandardseList.get(0), SerializerFeature.WriteMapNullValue), EaHotelstandard.class);
            map = checkJdWjbz(eaStandardVo,eaHotelstandard,eaHotelbookspersond);

            int controlintensity = eaHotelstandard.getControlintensity();  //控制类型,0刚性,1柔性
            if(controlintensity == 1){
                map.put("controlintensity",true);   //是否柔性提交
                map.put("code","0");
                return map;
            }else{
                if(map.get("code").equals("-1")){
                    map.put("reversalAmount",0);   //实际金额
                    map.put("controlintensity",false);   //是否柔性提交
                }else{
                    map.put("controlintensity",false);   //是否柔性提交
                }
                return map;
            }
        }else{
            //根据职级/职务/部门去查标准
            QueryWrapper queryWrapper2 = new QueryWrapper();
            queryWrapper2.eq("relationtype",0);
            queryWrapper2.like("dept",deptid);
            queryWrapper2.like("rankid",userIdentity);
            List<Map<String,Object>> eaStandardseList2 = eaHotelstandardMapper.selectMaps(queryWrapper2);
            if(eaStandardseList2.size() == 0){
                map.put("code","0");   //未指定酒店标准
                map.put("message","");   //提示信息:"用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "未指定酒店标准!"
                map.put("reversalAmount",eaHotelbookspersond.getAmount());   //实际金额
                map.put("controlintensity",false);   //是否柔性提交
                return map;
            }else{
                EaHotelstandard eaHotelstandard = JSON.parseObject(JSON.toJSONString(eaStandardseList2.get(0), SerializerFeature.WriteMapNullValue), EaHotelstandard.class);
                map = checkJdWjbz(eaStandardVo,eaHotelstandard,eaHotelbookspersond);

                int controlintensity = eaHotelstandard.getControlintensity();  //控制类型,0刚性,1柔性
                if(controlintensity == 1){
                    map.put("controlintensity",true);   //是否柔性提交
                    map.put("code","0");
                    return map;
                }else{
                    if(map.get("code").equals("-1")){
                        map.put("reversalAmount",0);   //实际金额
                        map.put("controlintensity",false);   //是否柔性提交
                    }else{
                        map.put("controlintensity",false);   //是否柔性提交
                    }
                    return map;
                }
            }
        }
    }

    //校验具体城市维护的酒店规则,城市等级维护的酒店规则
    private Map<String, Object> checkJdWjbz(EaStandardVo eaStandardVo,EaHotelstandard eaHotelstandard,EaHotelbookspersond eaHotelbookspersond) {
        Map<String,Object> map = new HashMap<String,Object>();
        String fpid = EmptyUtil.checkNull(eaStandardVo.getFpid());  //发票id
        //获取发票信息
        EaBill eaBill = eaBillMapper.selectById(fpid);
        Date kprq = eaBill.getDate();  //开票日期
        //获取月份
        String kpyf = String.valueOf(Integer.parseInt(String.format("%tm", kprq)));

        String regionid = EmptyUtil.checkNull(eaBill.getCity());  //目的地
        EaRegion eaRegion = eaRegionMapper.selectById(regionid);
        BigDecimal eaAmt = eaHotelbookspersond.getAmount();  //报销金额

        Date startdate = eaHotelbookspersond.getStartdate();   //开始日期
        Date enddate = eaHotelbookspersond.getEnddate();     //结束日期
        int days = 1;
        try {
            days = daysBetween(startdate,enddate) + 1;
        } catch (ParseException e) {
            e.printStackTrace();
        }

        eaAmt = eaAmt.divide(new BigDecimal(days),2,BigDecimal.ROUND_HALF_UP);    //报销金额除以天数,计算一天的报销金额

        BigDecimal firsttiercity = eaHotelstandard.getFirsttiercity(); //一线城市标准金额
        BigDecimal secondtiercity = eaHotelstandard.getSecondtiercity(); //二线城市标准金额
        BigDecimal thirdtiercity = eaHotelstandard.getThirdtiercity(); //三线城市标准金额
        BigDecimal fourthtiercity = eaHotelstandard.getFourthtiercity(); //四线城市标准金额
        BigDecimal hmttiercity = eaHotelstandard.getFirsttiercity(); //特别行政区标准金额

        //查询是否维护旺季标准
        Map<String,Object> eaHotelstaandarddtlParams = new HashMap<String,Object>();
        eaHotelstaandarddtlParams.put("zbid",eaHotelstandard.getId());     //主表id
        eaHotelstaandarddtlParams.put("provinceid",eaBill.getProvince());  //省份
        eaHotelstaandarddtlParams.put("cityid",eaBill.getCity());          //城市
        List<EaHotelstandarddtl> eaHotelstandarddtlList = eaHotelstandarddtlMapper.selectByMap(eaHotelstaandarddtlParams);
        if(eaHotelstandarddtlList != null && eaHotelstandarddtlList.size() > 0){
            EaHotelstandarddtl eaHotelstandarddtl = eaHotelstandarddtlList.get(0);
            String busyseasonmonth = EmptyUtil.checkNull(eaHotelstandarddtl.getBusyseasonmonth());  //旺季月份
            BigDecimal busyseasonstandard = eaHotelstandarddtl.getBusyseasonstandard();  //旺季报销金额
            BigDecimal slackseasonstandard = eaHotelstandarddtl.getSlackseasonstandard();  //普通报销金额
            if(busyseasonmonth.contains(kpyf)){   //在旺季月份,采取不一样的报销标准
                if(eaAmt.compareTo(busyseasonstandard) > 0){//刚性控制,不允许超标
                    map.put("code","-1");   //超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,不符合旺季下城市酒店报销标准:" + busyseasonstandard + "/天!");   //提示信息
                    map.put("reversalAmount",busyseasonstandard.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }else{
                    map.put("code","0");   //未超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,符合旺季下城市酒店报销标准:" + busyseasonstandard + "/天!");   //提示信息
                    map.put("reversalAmount",eaAmt.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }
            }else{  //不在旺季月份,取普通报销金额
                if(eaAmt.compareTo(slackseasonstandard) > 0){//刚性控制,不允许超标
                    map.put("code","-1");   //超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,不符合城市酒店报销标准:" + slackseasonstandard + "/天!");   //提示信息
                    map.put("reversalAmount",slackseasonstandard.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }else{
                    map.put("code","0");   //未超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,符合城市酒店报销标准:" + slackseasonstandard + "/天!");   //提示信息
                    map.put("reversalAmount",eaAmt.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }
            }
        }else{   //未维护单独的城市标准
            //城市等级标准
            String citylevel = eaRegion.getCitylevel();   //城市等级:FirstTierCity/SecondTierCity/ThirdTierCity/HMTCity
            if(citylevel.equals("FirstTierCity")){//一级城市
                if(eaAmt.compareTo(firsttiercity) > 0){//刚性控制,不允许超标
                    map.put("code","-1");   //超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,不符合一级城市酒店报销标准:" + firsttiercity + "/天!");   //提示信息
                    map.put("reversalAmount",firsttiercity.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }else{
                    map.put("code","0");   //未超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,符合一级城市酒店报销标准:" + firsttiercity + "/天!");   //提示信息
                    map.put("reversalAmount",eaAmt.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }
            }else if(citylevel.equals("SecondTierCity")){//二级城市
                if(eaAmt.compareTo(secondtiercity) > 0){//刚性控制,不允许超标
                    map.put("code","-1");   //超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,不符合二级城市酒店报销标准:" + secondtiercity + "/天!");   //提示信息
                    map.put("reversalAmount",secondtiercity.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }else{
                    map.put("code","0");   //未超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,符合二级城市酒店报销标准:" + secondtiercity + "/天!");   //提示信息
                    map.put("reversalAmount",eaAmt.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }
            }else if(citylevel.equals("ThirdTierCity")){//三级城市
                if(eaAmt.compareTo(thirdtiercity) > 0){//刚性控制,不允许超标
                    map.put("code","-1");   //超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,不符合三级城市酒店报销标准:" + thirdtiercity + "/天!");   //提示信息
                    map.put("reversalAmount",thirdtiercity.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }else{
                    map.put("code","0");   //未超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,符合三级城市酒店报销标准:" + thirdtiercity + "/天!");   //提示信息
                    map.put("reversalAmount",eaAmt.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }
            }else if(citylevel.equals("FourTierCity")){//四级城市
                if(eaAmt.compareTo(fourthtiercity) > 0){//刚性控制,不允许超标
                    map.put("code","-1");   //超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,不符合三级城市酒店报销标准:" + fourthtiercity + "/天!");   //提示信息
                    map.put("reversalAmount",fourthtiercity.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }else{
                    map.put("code","0");   //未超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,符合三级城市酒店报销标准:" + fourthtiercity + "/天!");   //提示信息
                    map.put("reversalAmount",eaAmt.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }
            }else if(citylevel.equals("HMTCity")){//特别行政区
                if(eaAmt.compareTo(hmttiercity) > 0){//刚性控制,不允许超标
                    map.put("code","-1");   //超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,不符合特别行政区酒店报销标准:" + hmttiercity + "/天!");   //提示信息
                    map.put("reversalAmount",hmttiercity.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }else{
                    map.put("code","0");   //未超标
                    map.put("message","用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "报销金额:" + eaAmt + "/天,符合特别行政区酒店报销标准:" + hmttiercity + "/天!");   //提示信息
                    map.put("reversalAmount",eaAmt.multiply(new BigDecimal(days)));   //实际金额
                    return map;
                }
            }else{
                map.put("code","0");   //未知等级城市,直接提示
                map.put("message","未知等级城市,请维护!");   //提示信息
                return map;
            }
        }
    }

    //交通
    public Map<String,Object> checkJtbz(EaStandardVo eaStandardVo){
        Map<String,Object> map = new HashMap<String,Object>();
        String fpid = eaStandardVo.getFpid();  //发票id
        //获取发票信息
        EaBill eaBill = eaBillMapper.selectById(fpid);
        String fplx = eaBill.getType();//发票类型:当消费类型为交通时,根据发票类型(火车票,机票,客运汽车,船票,收费公路通行费增值税电子普通发票,出租车发票,滴滴出行行程单)判断报销标准
        String fygsr = eaStandardVo.getFygsrid();  //费用归属人
        NcPersonnel ncPersonnel = ncPersonnelMapper.selectById(fygsr); // 人员信息

        if(fplx.equals("10503")){//火车票
            String seat = EmptyUtil.checkNull(eaBill.getSeat());  //火车座位类型:一等座/二等座/坐票
            // 查询对应组织和级别的火车标准是否设置
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("companycode",ncPersonnel.getPkOrg());
            queryWrapper.eq("level",ncPersonnel.getLevel());
            List<EaTrainstandard> eaTrainstandards = eaTrainstandardMapper.selectMaps(queryWrapper);
            if(eaTrainstandards.size() > 0){ // 有火车标准
                EaTrainstandard eaTrainstandard = JSON.parseObject(JSON.toJSONString(eaTrainstandards.get(0), SerializerFeature.WriteMapNullValue), EaTrainstandard.class);
                map = checkHcbz(eaTrainstandard,seat,fygsr);
                int controlintensity = eaTrainstandard.getControlintensity();  //控制类型,0刚性,1柔性
                if(map.get("code").equals("-2")){
                    map.put("code","-1");
                    map.put("reversalAmount",0);   //报销金额
                    map.put("controlintensity",false);   //是否柔性控制
                    return map;
                }else if(map.get("code").equals("-1")){
                    if(controlintensity == 1){
                        map.put("code","0");
                        map.put("reversalAmount",0);   //报销金额
                        map.put("message",map.get("message").toString() + "柔性控制");
                        map.put("controlintensity",true);   //是否柔性控制
                        return map;
                    }else{
                        map.put("reversalAmount",0);   //报销金额
                        map.put("controlintensity",false);   //是否柔性控制
                        return map;
                    }
                }else{
                    map.put("reversalAmount",eaBill.getTotal());   //报销金额
                    map.put("controlintensity",false);   //是否柔性控制
                    return map;
                }
            }else{
                map.put("code","0");
                map.put("message","");//"用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "未指定火车标准!"
                map.put("reversalAmount",eaBill.getTotal());   //报销金额
                map.put("controlintensity",false);   //是否柔性控制
                return map;
            }
        }else if(fplx.equals("10506")){//飞机票
            Map<String,Object> billItemParams = new HashMap<String,Object>();
            billItemParams.put("pid",fpid);
            List<EaBillItem> eaBillItemList = eaBillItemMapper.selectByMap(billItemParams);
            if(eaBillItemList.size() > 0){
                String international_flag = eaBill.getInternationalFlag();    //国内国际标签:国内(D)
                String seat = eaBillItemList.get(0).getClassName();  //飞机舱位等级:经济舱,商务舱,头等舱
                //根据组织 级别 去查标准
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("companycode",ncPersonnel.getPkOrg());
                queryWrapper.eq("level",ncPersonnel.getLevel());
                List<Map<String,Object>> eaAirplanestandardsList  = eaAirplanestandardMapper.selectMaps(queryWrapper);
                if(eaAirplanestandardsList.size() > 0){// 有设置标准
                    EaAirplanestandard eaAirplanestandard = JSON.parseObject(JSON.toJSONString(eaAirplanestandardsList.get(0), SerializerFeature.WriteMapNullValue), EaAirplanestandard.class);
                    map = checkFjbz(eaAirplanestandard,fygsr,seat,international_flag);
                    int controlintensity = eaAirplanestandard.getControlintensity();  //控制类型,0刚性,1柔性

                    if(map.get("code").equals("-2")){
                        map.put("reversalAmount",0);   //报销金额
                        map.put("code","-1");
                        map.put("controlintensity",false);   //是否柔性控制
                        return map;
                    }else if(map.get("code").equals("-1")){
                        if(controlintensity == 1){
                            map.put("code","0");
                            map.put("reversalAmount",0);   //报销金额
                            map.put("message",map.get("message").toString());
                            map.put("controlintensity",true);   //是否柔性控制
                            return map;
                        }else{
                            map.put("reversalAmount",0);   //报销金额
                            map.put("controlintensity",false);   //是否柔性控制
                            return map;
                        }
                    }else{
                        map.put("reversalAmount",eaBill.getTotal());   //报销金额
                        map.put("controlintensity",false);   //是否柔性控制
                        return map;
                    }
                }else {
                    // 没有设置标准
                    map.put("code","0");
                    map.put("message","");//"用户:" + changeIdToNameUtil.getNameById(eaStandardVo.getFygsrid()) + "未指定飞机标准!"
                    map.put("reversalAmount",eaBill.getTotal());   //报销金额
                    map.put("controlintensity",false);   //是否柔性控制
                    return map;
                }
            }

            //items数据为空时,提示
            map.put("code","0");
            map.put("controlintensity",false);   //是否柔性控制
            map.put("message","飞机明细为空!");
            return map;
        }else{ //其它的交通标准判断
            map.put("code","0");
            map.put("message","除了火车票/飞机票以外的交通发票暂时不做控制!");   //提示信息:"除了火车票/飞机票以外的交通发票暂时不做控制!"
            map.put("reversalAmount",eaBill.getTotal());   //报销金额
            map.put("controlintensity",false);   //是否柔性控制
            return map;
        }
    }

    // 校验飞机标准
    private Map<String, Object> checkFjbz(EaAirplanestandard eaAirplanestandard, String fygsr, String seat, String international_flag) {
        Map<String,Object> map = new HashMap<String,Object>();

        String domesticflights = eaAirplanestandard.getDomesticflights();  //国内航班座位等级
        String internationalflights = eaAirplanestandard.getInternationalflights();  //国际航班座位等级
        String isDomesticflights = eaAirplanestandard.getIsDomesticflights();  //是否允许乘坐国内航班:1不允许,2允许
        String isInternationalflights = eaAirplanestandard.getIsInternationalflights();  //是否允许乘坐国际航班:1不允许,2允许

        Map<String,Object> planeMap = getDictItemById(seat);  //获取乘坐的飞机字典数据
        String seatValue = planeMap.get("item_value") != null ? planeMap.get("item_value").toString() : "";
        String seatName = planeMap.get("item_text") != null ? planeMap.get("item_text").toString() : "";   //飞机-经济舱(座位等级)

        if(international_flag.equals("D")){  //国内航班
            if(isDomesticflights.equals("1")){  //不允许乘坐国内航班
                map.put("code","-2");
                map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐国内航班");   //提示信息
                return map;
            }else{  //允许乘坐国内航班
                if(!domesticflights.contains(seatValue)){//判断座位等级是否限制
                    map.put("code","-1");
                    map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐国内航班:" + seatName + "!");   //提示信息
                    return map;
                }else{
                    map.put("code","0");
                    map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "允许乘坐国内航班:" + seatName + "!");   //提示信息
                    return map;
                }
            }
        }else{//国际航班
            if(isInternationalflights.equals("1")){  //不允许乘坐国际航班
                map.put("code","-2");
                map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐国际航班!");   //提示信息
                return map;
            }else{
                if(!internationalflights.contains(seatValue)){//判断座位等级是否限制
                    map.put("code","-1");
                    map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐国际航班:" + seatName + "!");   //提示信息
                    return map;
                }else{
                    map.put("code","0");
                    map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "允许乘坐国际航班:" + seatName + "!");   //提示信息
                    return map;
                }
            }
        }
    }

    //校验火车标准
    private Map<String, Object> checkHcbz(EaTrainstandard eaTrainstandard,String seat,String fygsr) {
        Map<String, Object> map = new HashMap<String, Object>();

        int ishighspeedrailway = eaTrainstandard.getIshighspeedrailway(); //是否允许乘坐高铁:1不允许,2允许
        String highspeedrailway = eaTrainstandard.getHighspeedrailway(); //高铁座位类型:一等座/二等座/站票等
        int isbullettrain = eaTrainstandard.getIsbullettrain(); //是否允许乘坐动车:1不允许,2允许
        String bullettrain = eaTrainstandard.getBullettrain(); //动车座位类型:一等座/二等座/站票等
        int istrain = eaTrainstandard.getIstrain(); //是否允许乘坐普通列车:1不允许,2允许
        String train = eaTrainstandard.getTrain(); //普通列车座位类型:一等座/二等座/站票等

        Map<String,Object> trainTypeMap = getDictItemById(seat);  //获取乘坐的火车类型:高铁/动车/普通列车
        String trainType = trainTypeMap.get("dict_name") != null ? trainTypeMap.get("dict_name").toString() : "";   //高铁-动车-普通列车
        String seatValue = trainTypeMap.get("item_value") != null ? trainTypeMap.get("item_value").toString() : "";  //高铁-动车-普通列车(座位等级value)
        String seatName = trainTypeMap.get("item_text") != null ? trainTypeMap.get("item_text").toString() : "";   //高铁-动车-普通列车(座位等级)

        switch (trainType){
            case "高铁" :
                if(ishighspeedrailway == 1){
                    map.put("code","-2");
                    map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐高铁!");   //提示信息
                    return map;
                }else{
                    if(!highspeedrailway.contains(seatValue)){
                        map.put("code","-1");
                        map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐高铁:" + seatName + "!");   //提示信息
                        return map;
                    }else{
                        map.put("code","0");
                        map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "允许乘坐高铁:" + seatName + "!");
                        return map;
                    }
                }
            case "动车" :
                if(isbullettrain == 1){
                    map.put("code","-2");
                    map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐动车!");   //提示信息
                    return map;
                }else{
                    if(!bullettrain.contains(seatValue)){
                        map.put("code","-1");
                        map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐动车:" + seatName + "!");   //提示信息
                        return map;
                    }else{
                        map.put("code","0");
                        map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "允许乘坐动车:" + seatName + "!");
                        return map;
                    }
                }
            case "普通列车" :
                if(istrain == 1){
                    map.put("code","-2");
                    map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐普通列车!");   //提示信息
                    return map;
                }else{
                    if(!train.contains(seatValue)){
                        map.put("code","-1");
                        map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "不允许乘坐普通列车:" + seatName + "!");   //提示信息
                        return map;
                    }else{
                        map.put("code","0");
                        map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) +  "允许乘坐普通列车:" + seatName + "!");
                        return map;
                    }
                }
            default :
                map.put("code","0");
                map.put("message","未知异常!");   //提示信息
                return map;
        }
    }

    //查询字典表
    public Map<String,Object> getDictItemById(String seat){
        Map<String,Object> map = eaTrainstandardMapper.getDictItemById(seat);
        return map;
    }

    /**
     * 计算两个日期之间相差的天数
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate,Date bdate) throws ParseException
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        smdate=sdf.parse(sdf.format(smdate));
        bdate=sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    //判断招待费报销标准
    @Override
    public Map<String,Object> checkEntertain(EaEntertainCheckVo eaEntertainCheckVo){
        Map<String,Object> returnMap = new HashMap<String,Object>();

        String receptionType = eaEntertainCheckVo.getReceptionType();   //1公务接待,2商务接待
        BigDecimal personCount = eaEntertainCheckVo.getReceptionNum();  //接待人数
        BigDecimal amount2 = eaEntertainCheckVo.getAmount();             //总金额

        //判断报销金额是否符合标准:商务接待-600,公务接待150
        Map<String, Object> dictItem_sw = eaTrainstandardMapper.getDictItemById("1410435522261612223");
        Map<String, Object> dictItem_gw = eaTrainstandardMapper.getDictItemById("1410435522261612221");

        if(receptionType.equals("1")){  //公务接待
            String item_value = EmptyUtil.checkNull(dictItem_gw.get("item_value"));

            if(personCount.compareTo(new BigDecimal(0)) == 0){
                returnMap.put("message","公务接待报销标准:" + item_value + "/人");
                returnMap.put("reversalAmount",new BigDecimal(0));
                return returnMap;
            }
            BigDecimal amount = amount2.divide(personCount,2, BigDecimal.ROUND_HALF_UP);    //报销金额

            if(new BigDecimal(item_value).compareTo(amount) < 0){
                returnMap.put("message","报销金额:" + amount + "/人,超过公务接待报销标准:" + item_value + "/人");
                returnMap.put("reversalAmount",new BigDecimal(item_value).multiply(personCount));
                return returnMap;
            }else{
                returnMap.put("message","报销金额:" + amount + "/人,符合公务接待报销标准:" + item_value + "/人");
                returnMap.put("reversalAmount", amount2);
                return returnMap;
            }
        }else{  //商务接待
            String item_value = EmptyUtil.checkNull(dictItem_sw.get("item_value"));

            if(personCount.compareTo(new BigDecimal(0)) == 0){
                returnMap.put("message","商务接待报销标准:" + item_value + "/人");
                returnMap.put("reversalAmount",new BigDecimal(0));
                return returnMap;
            }
            BigDecimal amount = amount2.divide(personCount,2, BigDecimal.ROUND_HALF_UP);    //报销金额

            if(new BigDecimal(item_value).compareTo(amount) < 0){
                returnMap.put("message","报销金额:" + amount + "/人,超过商务接待报销标准:" + item_value + "/人");
                returnMap.put("reversalAmount",new BigDecimal(item_value).multiply(personCount));
                return returnMap;
            }else{
                returnMap.put("message","报销金额:" + amount + "/人,符合商务接待报销标准:" + item_value + "/人");
                returnMap.put("reversalAmount", amount2);
                return returnMap;
            }
        }
    }

    //判断是否制定报销标准-通讯费
    @Override
    public Map<String,Object> check_tx(EaStandardVo eaStandardVo){
        //判断报销控制标准
        String fpid = eaStandardVo.getFpid();  //发票id
        EaBill eaBill = eaBillMapper.selectById(fpid);
        String fygsr = eaStandardVo.getFygsrid();  //费用归属人 人员主键

        Map<String,Object> map = new HashMap<String,Object>();

        // 查询费用归属人的人员信息
        NcPersonnel ncPersonnel = ncPersonnelMapper.selectById(fygsr);
        // 人员职级： 1、正职领导 2、副职领导 3、中层 4、一般员工
        String rank = EmptyUtil.checkNull(ncPersonnel.getRank());
        // 人员组织信息
        String orgCode = EmptyUtil.checkNull(ncPersonnel.getPkOrg());

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("companycode",orgCode);
        queryWrapper.eq("rankid",rank);

        List<EaCommunicationstandard> eaCommunicationstandards = eaCommunicationstandardMapper.selectMaps(queryWrapper);
        if (eaCommunicationstandards.size() > 0){ // 对应的组织和职级有设置标准
            // 获取当前发票金额
            String total = eaBill.getTotal() != null ? eaBill.getTotal() : "0";
            EaCommunicationstandard eaCommunicationstandard = JSON.parseObject(JSON.toJSONString(eaCommunicationstandards.get(0), SerializerFeature.WriteMapNullValue), EaCommunicationstandard.class);
            BigDecimal monthlystandard = eaCommunicationstandard.getMonthlystandard();   //月度标准

            // 超出个人标准
            if(new BigDecimal(total).compareTo(monthlystandard) > 0){
                map.put("code","0");
                map.put("reversalAmount",total);   //报销金额
//                map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) + "报销金额:" + total +  ",不符合通讯标准:" + monthlystandard);
                map.put("message","人员:" +changeIdToNameUtil.getPsnNameById(fygsr) + "每月的通讯标准为:" + monthlystandard);
                map.put("controlintensity",true);   //是否柔性控制
                return map;
            }else{
                map.put("code","0");
                map.put("reversalAmount",total);   //报销金额
                map.put("message","人员:" + changeIdToNameUtil.getPsnNameById(fygsr) +  "每月的通讯标准为:" + monthlystandard);
                map.put("controlintensity",true);   //是否柔性控制
                return map;
            }
        }else{ // 未设置标准
            map.put("code", "1");
            map.put("message", "");   //提示信息:"通讯报销标准不控制!"
            map.put("reversalAmount", eaBill.getTotal());        //实际金额
            map.put("controlintensity", false);   //是否柔性控制
            return map;
        }
    }

}
